package org.crown.project.api;

import com.baomidou.mybatisplus.enums.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.DbType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.toolkit.StringUtils;
import org.junit.Test;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

/**
 * API接口代码生成工具
 *
 * @author WuFengSheng on 2018/7/16.
 */
public class GenApiCode {

    /**
     * 模版生成
     */
    @Test
    public void test() {
        boolean isMysql = true;

        /**
         * 生成后文件保存位置
         */
        String outputDir = "/Users/wufengsheng/Desktop/";
        /**
         * 数据库表名
         */
        String[] tableNames = new String[]{"demo"};
        /**
         * 功能模块包名
         */
        String module = "demo";

        AutoGenerator mpg = new AutoGenerator();
        /**
         * 注入自定义配置，可以在 VM 中使用 cfg.abc 设置的值
         * 模板里面用自定义参数：${cfg.abc}
         * --cfg是固定写法, 参考AbstractTemplateEngine.batchOutput()方法;
         * --abc就是map里put的参数名;
         */
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                Map<String, Object> map = new HashMap<String, Object>();
                map.put("abc", this.getConfig().getGlobalConfig().getAuthor() + "-mp");
                this.setMap(map);
            }
        };

        /**
         * 策略配置
         */
        StrategyConfig strategyConfig = new StrategyConfig();
        strategyConfig.setRestControllerStyle(true)
                // 启用lombok
                .setEntityLombokModel(true)
                .setEntityBuilderModel(true)
                // 表前缀
//                .setTablePrefix(new String[]{"st_"})
                // 设置乐观锁字段
                .setVersionFieldName("version")
                // 逻辑删除
                .setLogicDeleteFieldName("deleted")
                // 表名生成策略（下划线转驼峰）
                .setNaming(NamingStrategy.underline_to_camel)
                // 生成指定的表，注掉则生成所有表
                .setInclude(tableNames)


                /**
                 * 继承父类配置
                 */
                .setSuperControllerClass("org.crown.project.api.BaseApi")
                .setSuperServiceClass("org.crown.framework.service.BaseService")
                .setSuperServiceImplClass("org.crown.framework.service.impl.BaseServiceImpl")
                .setSuperMapperClass("org.crown.framework.mapper.BaseMapper")
                .setSuperEntityClass("org.crown.project.api.BaseApiEntity");
        mpg.setStrategy(strategyConfig);

        /**
         * 包配置
         */
        PackageConfig packageConfig = new PackageConfig()
                // 父级包名
//        .setParent("com.visitor.modules")
//        .setController("web")
//        .setService("service")
//        .setServiceImpl("impl")
//        .setMapper("mapper")
//        .setEntity("model.entity")
//        .setXml("mapper");

                .setParent("org.crown.project.api.module")
                .setMapper(module + ".mapper")
                .setServiceImpl(module + ".service.impl")
                .setService(module + ".service")
                .setController(module + ".controller")
                .setEntity(module + ".domain")
                .setXml(module + ".xml");
        mpg.setPackageInfo(packageConfig);

        /**
         * 全局配置
         */
        GlobalConfig gc = new GlobalConfig()
                // author
                .setAuthor("WuFengSheng")
                // 保存目录
                .setOutputDir(outputDir)
                .setFileOverride(true)
                // 是否生成pkVal()
                .setActiveRecord(false)
                // XML 二级缓存
                .setEnableCache(false)
                // XML ResultMap
                .setBaseResultMap(true)
                // XML columList
                .setBaseColumnList(true)
                // 主键类型
                .setIdType(IdType.AUTO);

        /**
         * 自定义文件（类名）命名，注意 %s 会自动填充表实体属性！
         */
//        gc.setControllerName("%sController")
//        .setServiceName("I%sService")
//        .setServiceImplName("%sImpl")
//        .setMapperName("%sMapper")
//        .setXmlName("%sMapper");

        gc.setMapperName("%sMapper");
        gc.setXmlName("%sMapper");
        gc.setServiceName("%sService");
        gc.setServiceImplName("%sServiceImpl");
        gc.setControllerName("%sApi");
        mpg.setGlobalConfig(gc);

        /**
         * 数据源配置
         */
        DataSourceConfig dsc = new DataSourceConfig();
        if (isMysql) {
            dsc.setDbType(DbType.MYSQL);
//            dsc.setDriverName("com.mysql.jdbc.Driver");
            dsc.setDriverName("com.mysql.cj.jdbc.Driver");
            dsc.setUsername("root");
//            dsc.setPassword("123456");
            dsc.setPassword("Ysb_Jsb@2018");
//            dsc.setUrl("jdbc:mysql://127.0.0.1:3306/crown2?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=UTC");
            dsc.setUrl("jdbc:mysql://192.168.1.248:3306/crown2?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=UTC");
        } else {
            dsc.setDbType(DbType.ORACLE);
            dsc.setDriverName("oracle.jdbc.driver.OracleDriver");
            dsc.setUsername("ybf_acq");
            dsc.setPassword("ybf_acq_jsb_2017");
            dsc.setUrl("jdbc:oracle:thin:@192.168.1.228:1521:orcl");
        }

        dsc.setTypeConvert(new MySqlTypeConvert() {
            // 自定义数据库表字段类型转换【可选】
            @Override
            public DbColumnType processTypeConvert(String fieldType) {
                // varchar(64)
                System.out.println("转换类型：" + fieldType);
                // 注意！！processTypeConvert 存在默认类型转换，如果不是你要的效果请自定义返回、非如下直接返回。
                return super.processTypeConvert(fieldType);
            }
        });
        mpg.setDataSource(dsc);

        /**
         * 自定义模板配置，可以 copy 源码 mybatis-plus/src/main/resources/templates 下面内容修改，
         * 放置自己项目的 src/main/resources/templates 目录下, 默认名称可以不配置，也可以自定义模板名称
         */
        TemplateConfig templateConfig = new TemplateConfig()
                .setController("/apiCodeTemplates/controller.java")
                .setServiceImpl("/apiCodeTemplates/impl.java")
                .setService("/apiCodeTemplates/iservice.java")
                .setMapper("/apiCodeTemplates/mapper.java")
                .setEntity("/apiCodeTemplates/model.java")
                .setXml("/apiCodeTemplates/mapper.xml");

        // 如上任何一个模块如果设置 空 OR Null 将不生成该模块。
        // 生成器配置自定义模板路径
        mpg.setTemplate(templateConfig);


        /**
         * 配置自定义 xxList.vue 生成
         */
//        List<FileOutConfig> focList = new ArrayList<FileOutConfig>();
//        focList.add(new FileOutConfig("/templates/dao.java.vm") {
//            @Override
//            public String outputFile(TableInfo tableInfo) {
//                return getGeneratorPath(outputDir + packageConfig.getParent() + "/dao", tableInfo, "Dao.java");
//            }
//        });
//
//        focList.add(new FileOutConfig("/templates/listvue.vue.vm") {
//            @Override
//            public String outputFile(TableInfo tableInfo) {
//                return getGeneratorPath(outputDir, tableInfo, ".vue");
//            }
//        });
//
//        cfg.setFileOutConfigList(focList);
        // 生成器配置自定义参数
//        mpg.setCfg(cfg);

        /**
         * 生成代码
         */
        mpg.execute();
    }

    /**
     * 生成的文件名
     */
    private static String getGeneratorPath(String outputDir, TableInfo tableInfo, String suffixPath) {
        String name = StringUtils.capitalize(tableInfo.getEntityName());
        String path = outputDir.replace(".", "/") + "/" + name + suffixPath;
        File outDir = new File(path).getParentFile();
        if (!outDir.exists()) {
            outDir.mkdirs();
        }
        return path;
    }
}
